#include <iostream>
#include <fcntl.h>
#include <sys/mman.h>
#include <unistd.h>
#include <cstring>
#include <semaphore.h>

#define SHM_NAME1 "/shm_data1"  // 共享内存 1 的名称
#define SHM_NAME2 "/shm_data2"  // 共享内存 2 的名称

// 定义共享资源结构体
typedef struct {
    sem_t semaphore;         // 未命名信号量
    char message[100];       // 消息存储
} SharedResource;

int main() {
    // 创建和初始化共享内存区 1 和 2
    int shm_fd1 = shm_open(SHM_NAME1, O_CREAT | O_RDWR, 0666);
    int shm_fd2 = shm_open(SHM_NAME2, O_CREAT | O_RDWR, 0666);
    if (shm_fd1 == -1 || shm_fd2 == -1) {
        std::cerr << "Failed to open shared memory." << std::endl;
        return 1;
    }

    // 设置共享内存大小
    ftruncate(shm_fd1, sizeof(SharedResource));
    ftruncate(shm_fd2, sizeof(SharedResource));

    // 映射共享内存区
    SharedResource* resource1 = (SharedResource*)mmap(nullptr, sizeof(SharedResource), PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd1, 0);
    SharedResource* resource2 = (SharedResource*)mmap(nullptr, sizeof(SharedResource), PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd2, 0);
    if (resource1 == MAP_FAILED || resource2 == MAP_FAILED) {
        std::cerr << "Failed to map shared memory." << std::endl;
        return 1;
    }
    std::cout << "Shared memory address in app: " << resource1 << std::endl;
    std::cout << "Shared memory data: " << resource1->message << std::endl;
    // 初始化未命名信号量
    sem_init(&resource1->semaphore, 1, 0); // 信号量共享（跨进程），初始值为 0
    sem_init(&resource2->semaphore, 1, 0); // 信号量共享（跨进程），初始值为 0

    // 程序 1 写数据到共享内存区 1
    std::cout << "Program 1: Enter a message: ";
    std::cin.getline(resource1->message, sizeof(resource1->message));
    std::cout << "Program 1: Sent message: " << resource1->message << std::endl;

    // 通知程序 2 数据已写入
    sem_post(&resource1->semaphore);

    // 等待程序 2 发送数据
    sem_wait(&resource2->semaphore);

    // 从共享内存区 2 读取数据并打印
    std::cout << "Program 1 received: " << resource2->message << std::endl;

    // 清理资源
    munmap(resource1, sizeof(SharedResource));
    munmap(resource2, sizeof(SharedResource));
    close(shm_fd1);
    close(shm_fd2);
    shm_unlink(SHM_NAME1);
    shm_unlink(SHM_NAME2);

    return 0;
}
